package svc

import (
	"time"

	"mall/service/attachment/rpc/attachmentclient"
	"mall/service/backend/common/gorseclient"
	"mall/service/backend/rpc/backendclient"
	"mall/service/blog/rpc/blogclient"
	"mall/service/forum/api/internal/config"
	"mall/service/forum/rpc/forumclient"
	"mall/service/order/rpc/orderclient"
	"mall/service/product/rpc/productclient"
	"mall/service/promotion/rpc/promotionclient"
	"mall/service/recommended/rpc/recommendedclient"
	"mall/service/setting/rpc/settingclient"
	"mall/service/user/rpc/userclient"

	"github.com/elastic/go-elasticsearch/v7"
	"github.com/hibiken/asynq"
	"github.com/silenceper/wechat/v2/miniprogram"
	"github.com/zeromicro/go-queue/kq"
	"github.com/zeromicro/go-zero/core/collection"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/core/stores/redis"
	"github.com/zeromicro/go-zero/zrpc"
)

const localCacheExpire = time.Second * 3600

type ServiceContext struct {
	Config config.Config

	AsynqClient *asynq.Client
	BizRedis    *redis.Redis
	EsClient    *elasticsearch.Client
	LocalCache  *collection.Cache
	MiniProgram *miniprogram.MiniProgram
	GorseClient gorseclient.GorseClient

	KqClient                           *kq.Pusher
	KqDeferredUpdateTradeStateClient   *kq.Pusher
	KqDeferredUpdateShoppingCartClient *kq.Pusher
	KqDeferredInquireAIClient          *kq.Pusher
	KqDistributePointsClient           *kq.Pusher

	AttachmentRpc  attachmentclient.Attachment
	BackendRpc     backendclient.Backend
	SettingRpc     settingclient.Setting
	BlogRpc        blogclient.Blog
	ForumRpc       forumclient.Forum
	ProductRpc     productclient.Product
	PromotionRpc   promotionclient.Promotion
	OrderRpc       orderclient.Order
	UserRpc        userclient.User
	RecommendedRpc recommendedclient.Recommended
}

func NewServiceContext(c config.Config) *ServiceContext {
	localCache, err := collection.NewCache(localCacheExpire)
	logx.Must(err)

	esClient, _ := newElasticClient(c)
	// logx.Must(err)

	rds := redis.MustNewRedis(c.BizRedis)

	return &ServiceContext{
		Config: c,

		AsynqClient: newAsynqClient(c),
		BizRedis:    rds,
		EsClient:    esClient,
		LocalCache:  localCache,
		MiniProgram: newMiniprogramClient(c),
		GorseClient: gorseclient.NewGorseClient(),

		KqClient: kq.NewPusher(
			c.KqForumReactionConf.Brokers,
			c.KqForumReactionConf.Topic,
		),
		KqDeferredUpdateTradeStateClient: kq.NewPusher(
			c.KqDeferredUpdateTradeStateConf.Brokers,
			c.KqDeferredUpdateTradeStateConf.Topic,
		),
		KqDeferredUpdateShoppingCartClient: kq.NewPusher(
			c.KqDeferredUpdateShoppingCartConf.Brokers,
			c.KqDeferredUpdateShoppingCartConf.Topic,
		),
		KqDeferredInquireAIClient: kq.NewPusher(
			c.KqDeferredInquireAIConf.Brokers,
			c.KqDeferredInquireAIConf.Topic,
		),
		KqDistributePointsClient: kq.NewPusher(
			c.KqDistributePointsConf.Brokers,
			c.KqDistributePointsConf.Topic,
		),
		AttachmentRpc:  attachmentclient.NewAttachment(zrpc.MustNewClient(c.AttachmentRpc)),
		BackendRpc:     backendclient.NewBackend(zrpc.MustNewClient(c.BackendRpc)),
		BlogRpc:        blogclient.NewBlog(zrpc.MustNewClient(c.BlogRpc)),
		ForumRpc:       forumclient.NewForum(zrpc.MustNewClient(c.ForumRpc)),
		ProductRpc:     productclient.NewProduct(zrpc.MustNewClient(c.ProductRpc)),
		PromotionRpc:   promotionclient.NewPromotion(zrpc.MustNewClient(c.PromotionRpc)),
		OrderRpc:       orderclient.NewOrder(zrpc.MustNewClient(c.OrderRpc)),
		SettingRpc:     settingclient.NewSetting(zrpc.MustNewClient(c.SettingRpc)),
		UserRpc:        userclient.NewUser(zrpc.MustNewClient(c.UserRpc)),
		RecommendedRpc: recommendedclient.NewRecommended(zrpc.MustNewClient(c.RecommendedRpc)),
	}
}
